package callgraph.process;

import callgraph.domain.JarConfig;
import callgraph.domain.ProfilingFilter;
import callgraph.dto.ClassInterfaceMethodInfo;
import callgraph.dto.ExtendsClassMethodInfo;
import callgraph.dto.MethodAttribute;

import java.io.BufferedWriter;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.jar.JarFile;

class AddInterfaceMethod4SuperClass extends CallGraphProcessor {


    public AddInterfaceMethod4SuperClass(CallGraphProcessStorage storage, ProfilingFilter profilingFilter, JarConfig jarConfig, JarFile jarFile, BufferedWriter resultWriter) {
        super(storage, profilingFilter, jarConfig, jarFile, resultWriter);
    }

    @Override
    public boolean handle() {
        for (Map.Entry<String, List<String>> childrenClassInfoEntry : storage.getChildrenClassInfoMap().entrySet()) {
            String superClassName = childrenClassInfoEntry.getKey();
            ExtendsClassMethodInfo extendsClassMethodInfo = storage.getExtendsClassMethodInfoMap().get(superClassName);
            if (extendsClassMethodInfo == null || !extendsClassMethodInfo.isAbstractClass()) {
                // 其他jar包中的Class可以找到，但是找不到它们的方法，是正常的情况
                continue;
            }
            ClassInterfaceMethodInfo classInterfaceMethodInfo = storage.getClassInterfaceMethodInfoMap().get(superClassName);
            if (Objects.isNull(classInterfaceMethodInfo)) {
                continue;
            }
            setMethodAttributeIfAbsent(extendsClassMethodInfo, classInterfaceMethodInfo);
        }
        return true;
    }

    private void setMethodAttributeIfAbsent(ExtendsClassMethodInfo extendsClassMethodInfo, ClassInterfaceMethodInfo classInterfaceMethodInfo) {
        MethodAttribute methodAttribute = MethodAttribute.builder()
                .abstractMethod(true)
                .publicMethod(true)
                .protectedMethod(false)
                .build();
        for (String interfaceName : classInterfaceMethodInfo.getInterfaceNameList()) {
            List<String> strings = storage.getInterfaceMethodWithArgsMap().get(interfaceName);
            if (strings != null) {
                for (String interfaceMethodWithArgs : strings) {
                    extendsClassMethodInfo.getMethodAttributeMap().putIfAbsent(interfaceMethodWithArgs, methodAttribute);
                }
            }
        }
    }

    @Override
    public CallGraphProcessor next() {
        return new RecordExtendsClassMethod(storage, profilingFilter, jarConfig, jarFile, resultWriter);
    }
}
